package dongze.com.ckdj.activity;

import android.Manifest;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.databinding.DataBindingUtil;
import android.databinding.Observable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridLayout;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import butterknife.BindView;
import butterknife.ButterKnife;
import dongze.com.ckdj.BR;
import dongze.com.ckdj.R;
import dongze.com.ckdj.dagger.component.VehicleComponent;
import dongze.com.ckdj.data.entity.request.AddMassLossRecordRequestBody;
import dongze.com.ckdj.data.entity.response.QueryMassLossResponse;
import dongze.com.ckdj.data.entity.response.User;
import dongze.com.ckdj.data.entity.response.VehicleInformationDetail;
import dongze.com.ckdj.databinding.InformationItemSpinnerBinding;
import dongze.com.ckdj.databinding.InformationItemTextBinding;
import dongze.com.ckdj.databinding.MassLossDataBinding;
import dongze.com.ckdj.databinding.MassLossPictureItemBinding;
import dongze.com.ckdj.databinding.model.InformationItemSpinnerModel;
import dongze.com.ckdj.databinding.model.InformationItemTextModel;
import dongze.com.ckdj.databinding.model.MassLossDataModel;
import dongze.com.ckdj.databinding.model.MassLossImageItemModel;
import dongze.com.ckdj.databinding.model.ProcessingModel;
import dongze.com.ckdj.map.MapUtil;
import dongze.com.ckdj.persistence.DaoHelper;
import dongze.com.ckdj.persistence.dao.DaoSession;
import dongze.com.ckdj.persistence.dao.ImageDao;
import dongze.com.ckdj.persistence.dao.ServerUploadTask;
import dongze.com.ckdj.persistence.dao.ServerUploadTaskDao;
import dongze.com.ckdj.service.IImageUploadCallback;
import dongze.com.ckdj.service.IImageUploadService;
import dongze.com.ckdj.service.ImageUploadService;
import dongze.com.ckdj.service.ImageUploadTask;
import dongze.com.ckdj.ui.ImageUploadDialog;
import dongze.com.ckdj.ui.StateDialog;
import dongze.com.ckdj.util.MyLog;
import dongze.com.ckdj.util.Util;
import io.reactivex.observers.DisposableObserver;


/**
 * Created by fanqwz on 2017/7/21.
 */

public class MassLossActivity extends ProgressableActivity {
    private static final String TAG = MassLossActivity.class.getSimpleName();
    private static final int PHOTO_INTENT = 1024;
    private static final int PERMISSION_REQUEST = 2048;
    private static final int IMAGE_COUNT = 9;
    private static final String IMAGE_PRIFIX = "massLoss";
    @BindView(R.id.static_content)
    ViewGroup mStaticContent;
    @BindView(R.id.mass_loss_container)
    ViewGroup mMassLossContainer;

    @Inject
    DaoSession daoSession;
    @Inject
    VehicleInformationDetail vehicleInformationDetail;
    @Inject
    User user;

    MapUtil mapUtil;
    IImageUploadService mService;

    Map<String, String> informations = new HashMap<>();
    MassLossDataModel massLossDataModel;
    Handler handler;
    QueryMassLossResponse reasonData;
    InformationItemSpinnerModel massLossRecordList = new InformationItemSpinnerModel();
    ProcessingModel processingModel = new ProcessingModel();
    MassLossImageItemModel[] imageModels = new MassLossImageItemModel[IMAGE_COUNT];
    File[] capturedImage = new File[IMAGE_COUNT];

    ServiceConnection mConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            MyLog.d(TAG, "onServiceConnected: ");
            mService = IImageUploadService.Stub.asInterface(service);
//            try {
//                mService.addCallback(mBinder);
//            } catch (RemoteException e) {
//                e.printStackTrace();
//            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            MyLog.d(TAG, "onServiceDisconnected: ");
//            try {
//                mService.removeCallback(mBinder);
//            } catch (RemoteException e) {
//                e.printStackTrace();
//            }
            mService = null;
        }
    };

//    IImageUploadCallback mBinder = new IImageUploadCallback.Stub() {
//
//        @Override
//        public void onTaskProgressChanged(ImageUploadTask task, int progress) throws RemoteException {
//            MyLog.d(TAG, "onTaskProgressChanged: " + task.getMassLossRecord());
//        }
//
//        @Override
//        public void onTaskFinished(ImageUploadTask task) throws RemoteException {
//            MyLog.d(TAG, "onTaskFinished: " + task.getMassLossRecord());
//        }
//    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        MyLog.d(TAG, "onCreate: ");
        mapUtil = new MapUtil(getAppCompenent());
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mass_loss);
        ButterKnife.bind(this);
        handler = new Handler(getMainLooper());

//        startService(new Intent(this, ImageUploadService.class));
        bindService(new Intent(this, ImageUploadService.class), mConn, BIND_AUTO_CREATE);

        if (getComponent(VehicleComponent.class) != null) {
            getComponent(VehicleComponent.class).inject(this);
        } else {
            finish();
            return;
        }

        Intent intent = getIntent();
        if (intent != null && intent.getExtras() != null) {
            informations.put("vin", intent.getExtras().getString("vin", ""));
            informations.put("brandName", intent.getExtras().getString("brandName", ""));
            informations.put("voyageNo", intent.getExtras().getString("voyageNo", ""));
            informations.put("model", intent.getExtras().getString("model", ""));
            informations.put("modelCode", intent.getExtras().getString("modelCode", ""));
            informations.put("userName", intent.getExtras().getString("userName", ""));
        } else {
            new AlertDialog.Builder(this)
                    .setTitle("错误")
                    .setMessage("没有传递extras数据")
                    .setCancelable(false)
                    .setNegativeButton("退出", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                        }
                    }).create()
                    .show();
        }

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            doInit();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == PERMISSION_REQUEST) {
            if (Arrays.asList(permissions).contains(Manifest.permission.WRITE_EXTERNAL_STORAGE) && grantResults[0] == PackageManager.PERMISSION_DENIED) {
                new AlertDialog.Builder(this)
                        .setTitle("权限错误")
                        .setMessage("没有读写外部存储设备权限！！")
                        .setCancelable(false)
                        .setNegativeButton("退出", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                finish();
                            }
                        })
                        .create()
                        .show();
            } else {
                doInit();
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private void doInit() {
        buildStaticContent();
        buildMassLossData();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.mass_loss, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.new_record) {
            newMassLossRecord();
        } else if (item.getItemId() == R.id.save_record) {
            saveMassLossRecord();
        } else if (item.getItemId() == R.id.delete_record) {
            deleteMassLossRecord();
        } else {
            return super.onOptionsItemSelected(item);
        }

        return true;
    }

    @Override
    protected void onDestroy() {
//        if (mService != null)
//            try {
//                mService.removeCallback(mBinder);
//            } catch (RemoteException e) {
//                e.printStackTrace();
//            }
        unbindService(mConn);
        mapUtil.dispose();
        super.onDestroy();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode >= PHOTO_INTENT && requestCode <= PHOTO_INTENT + IMAGE_COUNT && resultCode == RESULT_OK) {
            int offset = requestCode - PHOTO_INTENT;

            if (!capturedImage[offset].exists())
                return;

//            try {
//                BitmapFactory.Options o = new BitmapFactory.Options();
//                o.inSampleSize = 2;
//                Bitmap b = BitmapFactory.decodeFile(capturedImage[offset].getAbsolutePath(), o);
//                imageModels[offset].setImageFile(new BitmapDrawable(getResources(), b));
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
            imageModels[offset].setImageFile(capturedImage[offset].getAbsolutePath());
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    private void buildStaticContent() {
        String vehicleNumber = informations.get("vin");
        String voyageNumber = informations.get("voyage_no");

        if (vehicleNumber == null || voyageNumber == null) {
            MyLog.e(TAG, "buildStaticContent: vehicleNumber or voyageNumber is null");
        }

        InformationItemTextModel model = new InformationItemTextModel();
        model.setKey("航次");
        model.setValue(voyageNumber);
        addVehicleInfomationTextItem(model);

        model = new InformationItemTextModel();
        model.setKey("车架号");
        model.setValue(vehicleNumber);
        addVehicleInfomationTextItem(model);

        massLossRecordList.setKey("质损序列号");
        massLossRecordList.setValues(new String[]{"新纪录"});
        massLossRecordList.setPosition(0);
        massLossRecordList.addOnPropertyChangedCallback(massLossRecordSelected);
        addDropDownInfoItem(massLossRecordList);
    }

    private void addVehicleInfomationTextItem(InformationItemTextModel model) {
        InformationItemTextBinding binding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.information_item_text, mStaticContent, false);
        binding.setVehicleInformationItemText(model);
        mStaticContent.addView(binding.getRoot(), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    }

    private void addDropDownInfoItem(InformationItemSpinnerModel model) {
        InformationItemSpinnerBinding binding = DataBindingUtil.inflate(LayoutInflater.from(this), R.layout.information_item_spinner, mStaticContent, false);
        binding.setVehicleInformationItemSpinner(model);
        mStaticContent.addView(binding.getRoot(), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    }


    private void buildMassLossData() {
        View root = getLayoutInflater().inflate(R.layout.mass_loss_data, mMassLossContainer, false);
        mMassLossContainer.addView(root);
        MassLossDataBinding binding = DataBindingUtil.bind(root);
        massLossDataModel = new MassLossDataModel();
        binding.setMassLossData(massLossDataModel);
        binding.setProcessing(processingModel);
        massLossDataModel.reason.addOnPropertyChangedCallback(onReasonChanged);

        GridLayout imageContainer = (GridLayout) root.findViewById(R.id.mass_loss_image_container);
        for (int i = 0; i < IMAGE_COUNT; i++) {
            final int value = i;
            final MassLossImageItemModel image = new MassLossImageItemModel();
            image.setOnNewClicked(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!Util.checkCapturePermission(MassLossActivity.this))
                        return;

                    File file = Util.getImageFile(IMAGE_PRIFIX);
                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                    int currentapiVersion = android.os.Build.VERSION.SDK_INT;
                    if (currentapiVersion < 24) {
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
                        startActivityForResult(intent, PHOTO_INTENT + value);
                    } else {
                        Uri uri = FileProvider.getUriForFile(MassLossActivity.this, "dongze.com.ckdj.fileprovider", file);
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        startActivityForResult(intent, PHOTO_INTENT + value);
                    }
                    capturedImage[value] = file;
                }
            });
            image.setOnDeleteClicked(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    image.setImageFile(null);
                    capturedImage[value] = null;
                }
            });
            image.setOnImageClicked(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Util.ViewImage(MassLossActivity.this, capturedImage[value]);
                }
            });
            imageModels[i] = image;

            MassLossPictureItemBinding binding1 = DataBindingUtil.inflate(getLayoutInflater(), R.layout.mass_loss_picture_item, imageContainer, false);
            binding1.setMassLossImageItem(imageModels[i]);
            int width = getResources().getDisplayMetrics().widthPixels / 3-
                    getResources().getDimensionPixelSize(R.dimen.content_padding);
            GridLayout.LayoutParams params = new GridLayout.LayoutParams(new ViewGroup.LayoutParams(
                    width, width));

//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//                params.columnSpec = GridLayout.spec(i % 3, 1f);
//                params.rowSpec = GridLayout.spec(i / 3, 1f);
//            }
            imageContainer.addView(binding1.getRoot(), params);
        }
    }

    void newMassLossRecord() {
        massLossDataModel.reason.set(null);
        massLossDataModel.setEntries(null);
        massLossDataModel.setOnReasonClickListener(null);
        massLossDataModel.position.set("");
        massLossDataModel.level.set("");
        massLossRecordList.setPosition(0);

        for (MassLossImageItemModel m :
                imageModels) {
            m.setImageFile(null);
        }
    }

    void saveMassLossRecord() {
        String errString = "";
        if (massLossDataModel.reason.get() == null || massLossDataModel.reason.get().isEmpty() || reasonData == null
                || !massLossDataModel.reason.get().equals("" + reasonData.getDescription_cn() + " " + reasonData.getDescription_en())) {
            errString += "质损原因数据不正确\n";
        }

        if (massLossDataModel.position.get() == null
                || massLossDataModel.position.get().isEmpty()) {
            errString += "请选择质损位置\n";
        }

        if (massLossDataModel.level.get() == null
                || massLossDataModel.level.get().isEmpty()) {
            errString += "请选择质损程度\n";
        }

        if (!errString.isEmpty()) {
            new AlertDialog.Builder(this)
                    .setTitle("数据不完整")
                    .setMessage(errString)
                    .create()
                    .show();
            return;
        }


        AddMassLossRecordRequestBody body = new AddMassLossRecordRequestBody();
        body.setVin(informations.get("vin"));
        body.setBrand_name(informations.get("brandName"));
        body.setVoyage_no(informations.get("voyageNo"));
        body.setModel(informations.get("model"));
        body.setModel_code(informations.get("modelCode"));
        body.setUser_name(informations.get("userName"));
        body.setPosition(reasonData.getPosition());
        body.setDescription_cn(reasonData.getDescription_cn());
        body.setDescription_en(reasonData.getDescription_en());
        body.setLoss_level(massLossDataModel.level.get());
        body.setLoss_place(massLossDataModel.position.get());

        mapUtil.commitMassLossRecord(body, new DisposableObserver<Long>() {
            @Override
            protected void onStart() {
                super.onStart();
                doProcessing();
            }

            @Override
            public void onNext(Long value) {

                try {
                    if (Util.DISABLE.equals(Util.getPreference(getApplicationContext(), Util.PREF_UPLOAD_BACKGROUND, Util.DISABLE))) {
                        doUploadImage(value);
                    } else {
                        saveUploadImageRecordToService(value);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    new AlertDialog.Builder(MassLossActivity.this)
                            .setMessage("上传图片失败！！！！" + e.getMessage())
                            .create()
                            .show();
                }
            }

            @Override
            public void onError(Throwable e) {
                MyLog.e(TAG, "onError: ", e);
                finishProcessing();
                new AlertDialog.Builder(MassLossActivity.this)
                        .setMessage("文本数据上传失败。\n" + e.getMessage())
                        .create()
                        .show();
            }

            @Override
            public void onComplete() {
                finishProcessing();
            }
        });
    }

    void deleteMassLossRecord() {
        // TODO: 2017/8/2
    }

    void loadMassLossRecord(int position) {
        // TODO: 2017/8/2
        processingModel.visible.set(true);
    }

    //使用service，离线上传
    private void saveUploadImageRecordToService(Long massLossRecord) {
        final List<File> images = new ArrayList<>(capturedImage.length);

        for (int i = 0; i < capturedImage.length; i++) {
            if (capturedImage[i] != null)
                images.add(capturedImage[i]);
        }

        if (images.size() == 0) {
            finish();
            return;
        }

        if (mService != null) {
            try {
                for (int i = 0; i < images.size(); i++) {
                    ImageUploadTask task = DaoHelper.createMassLossTask(daoSession,
                            vehicleInformationDetail.getVin(),
                            user.getUser_name(),
                            String.valueOf(massLossRecord),
                            "img" + String.format("%02d", i + 1/*从1开始*/),
                            images.get(i).getAbsolutePath());
                    mService.addTask(task);
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        } else {
            new AlertDialog.Builder(this)
                    .setTitle("错误")
                    .setMessage("图片上传服务不可用,请重启app并重新录入数据！")
                    .create()
                    .show();
        }
    }

    //同步上传
    private void doUploadImage(final Long massLossRecord) {
        final List<File> images = new ArrayList<>(capturedImage.length);
        final List<ImageUploadTask> tasks = new ArrayList<>();

        for (int i = 0; i < capturedImage.length; i++) {
            if (capturedImage[i] != null)
                images.add(capturedImage[i]);
        }

        if (images.size() == 0) {
            finish();
            return;
        }

        for (int i = 0; i < images.size(); i++) {
            ImageUploadTask task = DaoHelper.createMassLossTask(daoSession,
                    vehicleInformationDetail.getVin(),
                    user.getUser_name(),
                    String.valueOf(massLossRecord),
                    "img" + String.format("%02d", i + 1/*从1开始*/),
                    images.get(i).getAbsolutePath());
            tasks.add(task);
        }

        ImageUploadDialog imageUploadDialog = new ImageUploadDialog(MassLossActivity.this, tasks, images, null);
        imageUploadDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {
                for (MassLossImageItemModel model :
                        imageModels) {
                    model.setImageFile(null);
                }

                for (int i = 0; i < capturedImage.length; i++) {
                    capturedImage[i] = null;
                }

                finish();
            }
        });
        imageUploadDialog.show();
    }

    private void updateImageRecord(final StateDialog dialog, final ImageUploadTask task, String massrecord, String imageIndex, final List<File> images, final IImageUploadCallback callback) {
        ServerUploadTask serverUploadTask = daoSession.getServerUploadTaskDao().queryBuilder().where(ServerUploadTaskDao.Properties.Id.eq(task.getId())).unique();

        if (serverUploadTask == null) {
            MyLog.e(TAG, "updateImageRecord: serverUploadTask id not exist");
            return;
        }

        mapUtil.updateMassLossImageRecord(
                massrecord,
                imageIndex,
                serverUploadTask.getImage().getServerPath(),
                informations.get("user_name"),
                new DisposableObserver<String>() {
                    @Override
                    protected void onStart() {
                        super.onStart();
                        dialog.addStateMessage("更新图片信息：" + task.getId());
                    }

                    @Override
                    public void onNext(String value) {
                        if ("success".equals(value)) {
                            dialog.addStateMessage(task.getId() + "更新信息OK。");


                            int founded = -1;
                            ImageDao imageDao = daoSession.getImageDao();
                            for (int i = 0; i < images.size(); i++) {
                                if (imageDao.queryBuilder().where(ImageDao.Properties.FilePath.eq(images.get(i).getAbsolutePath())).unique() != null) {
                                    founded = i;
                                    break;
                                }
                            }

                            if (founded != -1) {
                                images.remove(founded);
                            } else {
                                //  跟当前任务没关系
                                //dialog.addStateMessage("异常：上传的图片再当前任务图片列表中未找到！！！！");
                            }

                            if (images.size() == 0) {
                                dialog.addStateMessage("任务完成");
                                dialog.finish();
                                try {
                                    mService.removeCallback(callback);
                                } catch (RemoteException e) {
                                    e.printStackTrace();
                                }
                            }
                        } else {
                            dialog.critical(task.getId() + "更新信息失败");
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        dialog.critical(task.getId() + "更新信息失败，" + e.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    Observable.OnPropertyChangedCallback onReasonChanged = new Observable.OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(Observable sender, int propertyId) {
            if (massLossDataModel.reason.get() != null && massLossDataModel.reason.get().length() >= 4 && !massLossDataModel.reason.get().equals("查询中......")) {
                // prevent requery after select a drop down list item
                handler.removeCallbacks(updateReasonentriesRunnable);
                handler.postDelayed(updateReasonentriesRunnable, 800);
            }
        }
    };

    Runnable updateReasonentriesRunnable = new Runnable() {
        @Override
        public void run() {
            if (reasonData != null && (reasonData.getDescription_cn() + " " + reasonData.getDescription_en()).equals(massLossDataModel.reason.get()))
                // prevent trigered twice
                return;

            massLossDataModel.setEntries(new String[]{"查询中......"});
            mapUtil.queryMassLossReason(massLossDataModel.reason.get(),
                    new DisposableObserver<Pair<List<QueryMassLossResponse>, String[]>>() {
                        @Override
                        public void onNext(final Pair<List<QueryMassLossResponse>, String[]> value) {
                            MyLog.d(TAG, "queryMassLossReason::onNext: ");
                            massLossDataModel.setEntries(value.second);
                            massLossDataModel.setOnReasonClickListener(new AdapterView.OnItemClickListener() {
                                @Override
                                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                                    reasonData = value.first.get(position);
                                    massLossDataModel.reason.set(value.second[position]);
                                }
                            });
                        }

                        @Override
                        public void onError(Throwable e) {
                            MyLog.e(TAG, "onError: ", e);
                        }

                        @Override
                        public void onComplete() {

                        }
                    });
        }
    };

    Observable.OnPropertyChangedCallback massLossRecordSelected = new Observable.OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(Observable sender, int propertyId) {
            if (BR.position == propertyId) {
                loadMassLossRecord(massLossRecordList.getPosition());
            }
        }
    };
}
